package com.atldy.redis.controller;

import cn.hutool.core.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * <h2> TODO </h2>
 *
 * @Author: li-dong-yang
 * @CreateTime: 2021-11-13 23:22
 */
@RestController
@RequestMapping("/geo")
@Api(value = "redis  geo 地图相关功能", tags = "redis  geo 地图相关功能")
public class GeoController {

    public static final String CITY = "city";

    @Autowired
    private RedisTemplate redisTemplate;

    @ApiOperation(value = "添加地理坐标", notes = "添加地理坐标")
    @GetMapping("/geoAdd")
    public Boolean geoAdd() {
        Map<String, Object> map = new HashMap<>(16);
        map.put("天安门", new Point(116.403963, 39.915119));
        map.put("故宫", new Point(116.403414, 39.924091));
        map.put("长城", new Point(116.024067, 40.362639));
        Long add = redisTemplate.opsForGeo().add(CITY, map);
        return ObjectUtil.isEmpty(add);
    }

    @ApiOperation(value = "获取地理位置的坐标", notes = "获取地理位置的坐标")
    @GetMapping("/selectGeoList")
    public Point getGeoPoint(String cityName) {
        return (Point) redisTemplate.opsForGeo().position(CITY, cityName)
                .stream().findAny().orElse(null);
    }


    @ApiOperation(value = "获取地理位置的base32哈希值", notes = "获取地理位置的base32哈希值")
    @GetMapping("/getGeoHash")
    public String getGeoHash(String cityName) {
        return (String) redisTemplate.opsForGeo().hash(CITY, cityName)
                .stream().findAny().orElse(null);
    }

    @ApiOperation(value = "获取两地之间的距离", notes = "获取地理位置的坐标")
    @GetMapping("/getGeoDistance")
    public Distance getGeoDistance(String cityName1, String cityName2) {
        return redisTemplate.opsForGeo().distance(CITY, cityName1, cityName2
                , RedisGeoCommands.DistanceUnit.KILOMETERS);
    }

    /**
     * 通过经度，纬度查找附近的
     * 北京王府井位置116.418017,39.914402,这里为了方便讲课，故意写死
     */
    @ApiOperation("通过经度，纬度查找附近的")
    @RequestMapping(value = "/georadius", method = RequestMethod.GET)
    public GeoResults radiusByxy() {
        //这个坐标是北京王府井位置
        Circle circle = new Circle(116.418017, 39.914402, Metrics.MILES.getMultiplier());
        //返回50条
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs
                .newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(10);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = this.redisTemplate
                .opsForGeo().radius(CITY, circle, args);
        return geoResults;
    }

    /**
     * 通过地方查找附近
     */
    @ApiOperation("通过地方查找附近")
    @RequestMapping(value = "/georadiusByMember", method = RequestMethod.GET)
    public GeoResults radiusByMember() {
        String member = "天安门";
        //返回50条
        RedisGeoCommands.GeoRadiusCommandArgs args =
                RedisGeoCommands.GeoRadiusCommandArgs
                        .newGeoRadiusArgs().includeDistance()
                        .includeCoordinates().sortAscending().limit(10);
        //半径10公里内
        Distance distance = new Distance(10, Metrics.KILOMETERS);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = this.redisTemplate.opsForGeo()
                .radius(CITY, member, distance, args);
        return geoResults;
    }
}